<?php

require "conf.php";
require_once "application/exception/SqlException.php";
require_once "utils/Validate.php";

abstract class BaseDAO{
	
	//TODO: make this method private when all subclasses stop invoking it
	//TODO: throw a SqlException when unable to connect
	protected function connect(){
		$db= mysql_connect ("localhost", DBUSERNAME, DBPASSWORD) or die ('I cannot connect to the database because: ' . mysql_error());
    	mysql_select_db (DBNAME);
	}

	/**
	 * myqsl query method for returning Strings from the
	 * database
	 * 
	 * this method should be used when you expect a single string
	 * to be returned.  
	 * 
	 * request all of the fields in sql, then specifier the field
	 * you wish to receive the value of in 2nd parameter.
	 * 
	 * @param $sql
	 * @param $field
	 * @param $args optional
	 */
	public function queryForString($sql, array $args = null){
	
		if(!is_null($args)){
			// this protects against sql injection
			foreach($args as &$v){
				$v = mysql_real_escape_string($v);
			}
			$sql = vsprintf($sql, $args);
		}
		
		$this->connect();

		// this protects against sql injection
//		$sql = mysql_real_escape_string($sql);
		$find = mysql_query($sql);

		$result = mysql_fetch_assoc($find);
		$result = array_values((array) $result);

		if(count($result) > 1){
			throw new SqlException("result set greater than 1, when expecting " .
					"only one result");
		}
		
		$result = (string) $result[0];
		
		if(!is_string($result)){
			throw new SqlException("return result is not a string");
		}		
/*				
		if(! preg_match("/^[a-zA-Z0-9]{*}/", $result)){
			throw new SqlException("return result is not a string");
		}
	*/	
		return $result;
	}
	
	/**
	 * myqsl query method for returning an assoc array from the
	 * database
	 * 
	 * array(array([key] => "value1"), ...)
	 * 
	 * this method should be used when you expect a list of values
	 * to be returned.
	 * 
	 * @param $sql
	 * @param $args optional
	 */	
	public function queryForArray($sql, array $args = null){
		
		$this->connect();

		// this protects against sql injection
		$sql = mysql_real_escape_string($sql);
		
		$find = mysql_query($sql);

		$resultSet = array();
		
		while($row = mysql_fetch_assoc($find)){
		
			array_push($resultSet, $row);	
		}		
		
		return $resultSet;
	}
	
	/**
	 * myqsl query method for returning an array map from the
	 * database
	 * 
	 * array([key] => "value1", ...)
	 * 
	 * this method should be used when you expect a list of key value
	 * pairs to be returned.
	 * 
	 * @param $sql
	 */	
	public function queryForMap($sql){
		
		$this->connect();

		// this protects against sql injection
		$sql = mysql_real_escape_string($sql);
		
		$find = mysql_query($sql);
		$resultSet = array();
		
		// populate array map
		while($row = mysql_fetch_array($find)){
			
			$resultSet[$row[0]] = $row[1];	
		}		
		
		return $resultSet;
	}
	
	public function queryForObject($sql, $object){
		
		Validate::notNull($sql);
		Validate::notNull($object);
		
		$this->connect();
		
		$find = mysql_query($sql);
		$resultSet = array();

		$params = array();
		while($row = mysql_fetch_array($find)){
			for($i=0; $i<(count($row)/2); $i++){
				array_push($params, $row[$i]);
			}
		}

		$find = mysql_query($sql);
		$obj = mysql_fetch_object($find, $object, $params);
		
		return $obj;
	}
	
	public function update($sql, array $args = null){

		$this->connect();
				
		if(!is_null($args)){
			// this protects against sql injection
			foreach($args as &$v){
				$v = mysql_real_escape_string($v);
			}
			$sql = vsprintf($sql, $args);
		}
		
//		mysql_query returns false on error
		$query = mysql_query($sql);

		if(!$query){
			throw new SqlException("Error updating table, query failed!");
		}
	}
}
?>
